/**
 * dynamic-form.js
 * 单文件动态表单生成
 */
let DynamicForm = (function(){
    const esc=v=>(v===undefined||v===null?"":String(v).replace(/"/g,"&quot;"));
    return {
        containerId:null,
        fields:[],
        editors:{},
        values:{},

        render(containerId, fields, values={}){
            this.containerId = containerId;
            this.fields = fields || [];
            this.values = values || {};
            const container = document.getElementById(containerId);
            if(!container) return;
            container.innerHTML = "";
            this.fields.forEach(f=>{
                container.insertAdjacentHTML("beforeend", this.renderFieldHtml(f));
            });

            if(window.layui && layui.form) layui.form.render();
            this.initComponents();
            this.bindFieldChange();
            // this.setValues(this.values);
        },

        renderFieldHtml(f){
            const tipHtml = f.tip?`<tip>${f.tip}</tip>`:"";
            const verify = [];
            if(f.required) verify.push("required");
            if(f.minLength) verify.push(`minLength[${f.minLength}]`);
            if(f.maxLength) verify.push(`maxLength[${f.maxLength}]`);
            const layVerify = verify.join("|");
            switch(f.type){
                case "number":
                return `<div class="layui-form-item item_${f.name}${f.hide ? ' layui-hide' : ''} ${f.hide ? ' layui-hide' : ''}">
                            <label class="layui-form-label${f.required ? ' required' : ''}">${f.label}</label>
                            <div class="layui-input-block">
                                <input type="number" name="${f.name}" class="layui-input" placeholder="${esc(f.placeholder)}" lay-verify="${layVerify}" value="" ${f.disabled?' disabled':''}>
                            </div>
                        </div>`;
                case "save_btn":
                    return `<div class="layui-form-item">
                                <div class="layui-input-block">
                                    <button class="layui-btn layui-btn-normal" lay-submit lay-filter="saveBtn">${f.label}</button>
                                </div>
                            </div>`;
                case "text":
                    return `<div class="layui-form-item item_${f.name}${f.hide ? ' layui-hide' : ''}">
                            <label class="layui-form-label${f.required ? ' required' : ''}">${f.label}</label>
                                <div class="layui-input-block">
                                  <input type="text" name="${f.name}" class="layui-input" placeholder="${esc(f.placeholder)}" lay-verify="${layVerify}" ${f.disabled?' disabled':''}>
                                  ${tipHtml}
                                </div>
                            </div>`;
                case "textarea":
                    return `<div class="layui-form-item item_${f.name}${f.hide ? ' layui-hide' : ''}">
                                <label class="layui-form-label${f.required?' required':''}">${f.label}</label>
                                <div class="layui-input-block">
                                  <textarea name="${f.name}" class="layui-textarea" placeholder="${esc(f.placeholder)}" lay-verify="${layVerify}"></textarea>
                                  ${tipHtml}
                                </div>
                            </div>`;
                case "select":
                    return `<div class="layui-form-item item_${f.name}${f.hide ? ' layui-hide' : ''}">
                                <label class="layui-form-label${f.required?' required':''}">${f.label}</label>
                                <div class="layui-input-block">
                                  <select name="${f.name}" lay-verify="${layVerify}" lay-filter="filter_${f.name}">
                                    ${(f.options||[]).map(o=>`<option value="${esc(o.value)}">${esc(o.label)}</option>`).join("")}
                                  </select>
                                  ${tipHtml}
                                </div>
                           </div>`;
                case "radio":
                    return `<div class="layui-form-item item_${f.name}${f.hide ? ' layui-hide' : ''}">
                                <label class="layui-form-label${f.required?' required':''}">${f.label}</label>
                                <div class="layui-input-block">
                                ${(f.options||[]).map(r=>`<input type="radio" name="${f.name}" value="${esc(r.value)}" title="${esc(r.label)}" lay-verify="${layVerify}">`).join("")}
                                ${tipHtml}
                                </div>
                            </div>`;
                case "checkbox":
                    return `<div class="layui-form-item item_${f.name}${f.hide ? ' layui-hide' : ''}">
                                <label class="layui-form-label${f.required?' required':''}">${f.label}</label>
                                <div class="layui-input-block">
                                 ${(f.options||[]).map(r=>`<input type="checkbox" name="${f.name}" value="${esc(r.value)}" title="${esc(r.label)}" lay-verify="${layVerify}">`).join("")}
                                 ${tipHtml}
                                </div>
                            </div>`;
                case "switch":
                    return `<div class="layui-form-item item_${f.name}${f.hide ? ' layui-hide' : ''}">
                                <label class="layui-form-label${f.required?' required':''}">${f.label}</label>
                                <div class="layui-input-block">
                                    <input type="checkbox" name="${f.name}" lay-skin="switch" ${f.default?"checked":""}>
                                    ${tipHtml}
                                </div>
                            </div>`;
                case "editor":
                    return `<div class="layui-form-item item_${f.name}${f.hide ? ' layui-hide' : ''}">
                                <label class="layui-form-label${f.required?' required':''}">${f.label}</label>
                                <div class="layui-input-block">
                                    <div id="editor-${f.name}" style="height:${f.height||200}px;"></div>
                                    ${tipHtml}
                                </div>
                            </div>`;
                case "table":
                    return `<div class="layui-form-item item_${f.name}${f.hide ? ' layui-hide' : ''}">
                                <label class="layui-form-label${f.required?' required':''}">${f.label}</label>
                                <div class="layui-input-block">
                                      <table class="layui-table" id="table-${f.name}">
                                        <thead><tr>${(f.children||[]).map(c=>`<th>${c.label}</th>`).join("")}<th>操作</th></tr></thead>
                                        <tbody></tbody>
                                      </table>
                                  <button type="button" class="layui-btn layui-btn-sm" onclick="DynamicForm.addTableRow('${f.name}')">新增行</button>
                                  ${tipHtml}
                                </div>
                            </div>`;
                default: return "";
            }
        },

        getFieldValue(name){
            const el = document.querySelector(`[name="${name}"]`);
            if(!el) return null;
            if(el.type==="radio" || el.type==="checkbox"){
                const checked = Array.from(document.querySelectorAll(`[name="${name}"]:checked`));
                return el.type==="radio"? (checked.length>0?checked[0].value:null) : checked.map(c=>c.value);
            }
            return el.value;
        },

        bindFieldChange(){
            const _this = this;
            if(!window.layui || !layui.form) return;
            this.fields.forEach(f=>{
                ["select","radio","checkbox","switch"].forEach(type=>{
                    try{
                        layui.form.on(`${type}(${f.name})`, ()=>{ /* 不做显示隐藏 */ });
                    } catch(e){}
                });
            });
        },

        initComponents(){
            this.fields.forEach(f=>{
                if(f.type==="editor" && window.wangEditor){
                    const E = window.wangEditor;
                    const editor = new E(`#editor-${f.name}`);
                    editor.create();
                    this.editors[f.name]=editor;
                }
            });
        },

        // setValues(values){
        //     this.values = values || {};
        //     Object.keys(values).forEach(k=>{
        //         const val = values[k];
        //         const els = document.querySelectorAll(`[name="${k}"]`);
        //         els.forEach(el=>{
        //             if(el.type==="radio") el.checked=(el.value==val);
        //             else if(el.type==="checkbox") el.checked=(Array.isArray(val)?val.includes(el.value):el.value==val);
        //             else el.value = val;
        //         });
        //         if(this.editors[k]) this.editors[k].txt.html(val||"");
        //     });
        //     if(window.layui && layui.form) layui.form.render();
        // },

        addTableRow(tableName){
            const tableField = this.fields.find(f=>f.name===tableName);
            if(!tableField) return;
            const tbody = document.querySelector(`#table-${tableName} tbody`);
            if(!tbody) return;
            const tr = document.createElement("tr");
            tr.innerHTML = `${(tableField.children||[]).map(c=>`<td><input type="text" name="${c.name}" class="layui-input"${c.required?' lay-verify="required"':''}></td>`).join("")}<td><button type="button" onclick="this.closest('tr').remove()" class="layui-btn layui-btn-danger layui-btn-sm">删除</button></td>`;
            tbody.appendChild(tr);
        },

        validate(){
            let valid=true, messages=[];
            this.fields.forEach(f=>{
                if(f.required){
                    const val = this.getFieldValue(f.name);
                    if(val===null || val==="" || (Array.isArray(val) && val.length===0)){
                        valid=false;
                        messages.push(`${f.label} 为必填`);
                    }
                }
                if(f.minLength || f.maxLength){
                    const val = this.getFieldValue(f.name) || "";
                    if(f.minLength && val.length<f.minLength){
                        valid=false;
                        messages.push(`${f.label} 最小长度为${f.minLength}`);
                    }
                    if(f.maxLength && val.length>f.maxLength){
                        valid=false;
                        messages.push(`${f.label} 最大长度为${f.maxLength}`);
                    }
                }
            });
            return {valid, messages};
        },

        getValues(){
            const res = {};
            this.fields.forEach(f=>{
                if(f.type==="table"){
                    const rows=[];
                    const tbody = document.querySelector(`#table-${f.name} tbody`);
                    if(tbody) Array.from(tbody.querySelectorAll("tr")).forEach(tr=>{
                        const row={};
                        (f.children||[]).forEach(c=>{
                            const input = tr.querySelector(`[name="${c.name}"]`);
                            row[c.name]=input?input.value:"";
                        });
                        rows.push(row);
                    });
                    res[f.name]=rows;
                } else {
                    res[f.name]=this.getFieldValue(f.name);
                }
            });
            return res;
        }
    };
})();



/**
 * 动态表单填充值函数
 * 该函数根据提供的字段定义和数据详情，自动填充表单中的对应元素
 * @param {Object} body - 表单容器对象，通常是jQuery对象
 * @param {Object} detail - 包含表单字段值的数据对象
 * @param {Array} fields - 字段定义数组，每个字段包含name和type属性
 */
const DynamicFormFillValue = function(body, detail, fields) {
    fields.forEach(f => {
        let value = detail[f.name];
        if (value !== undefined && value !== null) {
            let selector = "[name='" + f.name + "']";
            switch (f.type) {
                case 'number':
                    body.find("input" + selector).val(value);
                    break;
                case 'text':
                    body.find("input" + selector).val(value);
                    break;
                case 'textarea':
                    body.find("textarea" + selector).val(value);
                    break;

                case 'radio':
                    // 清除并重新设置选中
                    body.find("input[type='radio']" + selector).prop('checked', false);
                    body.find("input[type='radio']" + selector + "[value='" + value + "']").prop('checked', true);
                    break;

                case 'select':
                    body.find("select" + selector).val(value);
                    break;

                case 'checkbox':
                    var $checkbox = body.find("input[type='checkbox']" + selector);
                    $checkbox.prop('checked', false);
                    if (Array.isArray(value)) {
                        value.forEach(function (val) {
                            $checkbox.filter("[value='" + val + "']").prop('checked', true);
                        });
                    } else if (value) {
                        $checkbox.filter("[value='" + value + "']").prop('checked', true);
                    }
                    break;

                case 'date':
                    // 日期输入框（Laydate 类型）
                    body.find("input" + selector).val(value);
                    break;
            }
        }
    });
}


/**
 * 格式化字段数据
 * @param {Array} fields - 需要格式化的字段数组
 * @returns {Array} 格式化后的字段数组
 */
function FormatFields(fields, key) {
    let detailFields = [];
    fields.forEach(function(field) {
        if (field.use?.includes(key)) {
            detailFields.push(field);
        }
    });
    return detailFields
}


window.DynamicForm = DynamicForm;


